
# 导入 json 模块，用于处理 JSON 数据
import json

# 从 qtpy 库导入 QtCore 和 QtGui 模块，用于处理 Qt 相关的核心功能和图形界面
from qtpy import QtCore, QtGui
# 从 qtpy.QtWidgets 模块导入所需的界面组件类
from qtpy.QtWidgets import (
    QListWidget,
    QListWidgetItem,
    QWidget,
    QAbstractItemView
)

# 从 src.UI.EditorHistory 模块导入 EditorHistory 类，用于管理编辑器的历史记录
from src.UI.EditorHistory import EditorHistory
# 从 src.UI.Canvas.UIVariable 模块导入 UIVariable 类，用于处理 UI 变量
from src.UI.Canvas.UIVariable import UIVariable
# 从 src.UI.Views.VariablesWidget_ui 模块导入 Ui_Form 类，用于加载界面布局
from src.UI.Views.VariablesWidget_ui import Ui_Form
# 从 src.Core.Common 模块导入所有内容，可能包含一些通用的常量和函数
from src.Core.Common import *

# 定义变量标签常量
VARIABLE_TAG = "VAR"
# 定义变量数据标签常量
VARIABLE_DATA_TAG = "VAR_DATA"


class VariablesListWidget(QListWidget):
    """
    VariablesListWidget 类继承自 QListWidget，用于显示变量列表，
    支持拖拽移动、单选等功能。
    """

    def __init__(self, parent=None):
        """
        初始化 VariablesListWidget 实例。

        :param parent: 父组件，默认为 None
        """
        # 调用父类 QListWidget 的构造函数
        super(VariablesListWidget, self).__init__(parent)
        # 设置拖拽模式为内部移动，不过此处存在未解析特性引用问题
        self.setDragDropMode(QAbstractItemView.InternalMove)
        # 设置默认的拖放动作，不过此处存在未解析特性引用问题
        self.setDefaultDropAction(QtCore.Qt.MoveAction)
        # 设置选择模式为单选，不过此处存在未解析特性引用问题
        self.setSelectionMode(QAbstractItemView.SingleSelection)
        # 设置选择矩形可见
        self.setSelectionRectVisible(True)

    def mousePressEvent(self, event):
        """
        处理鼠标按下事件，当点击列表项时，若该项有对应的组件，
        则创建拖拽对象并设置相关的 MIME 数据。

        :param event: 鼠标事件对象
        """
        # 调用父类的 mousePressEvent 方法处理鼠标按下事件
        super(VariablesListWidget, self).mousePressEvent(event)
        # 获取当前选中项的组件
        w = self.itemWidget(self.currentItem())
        if w:
            # 创建一个拖拽对象
            drag = QtGui.QDrag(self)
            # 创建一个 MIME 数据对象
            mime_data = QtCore.QMimeData()
            # 调用组件的 serialize 方法获取变量的 JSON 数据，不过此处存在未解析特性引用问题
            varJson = w.serialize()
            # 构建包含变量标签和变量数据的字典
            dataJson = {VARIABLE_TAG: True, VARIABLE_DATA_TAG: varJson}
            # 将字典转换为 JSON 字符串并设置到 MIME 数据中
            mime_data.setText(json.dumps(dataJson))
            # 将 MIME 数据设置到拖拽对象中
            drag.setMimeData(mime_data)
            # 执行拖拽操作
            drag.exec_()


class VariablesWidget(QWidget, Ui_Form):
    """
    VariablesWidget 类继承自 QWidget 和 Ui_Form，用于管理变量的创建、显示和更新，
    与 PyFlow 实例进行交互。
    """

    def __init__(self, pyFlowInstance, parent=None):
        """
        初始化 VariablesWidget 实例。

        :param pyFlowInstance: PyFlow 实例对象
        :param parent: 父组件，默认为 None
        """
        # 调用父类的构造函数
        super(VariablesWidget, self).__init__(parent)
        # 初始化界面布局
        self.setupUi(self)
        # 保存 PyFlow 实例对象
        self.pyFlowInstance = pyFlowInstance
        # 连接图形管理器的图形改变信号到 onGraphChanged 方法
        self.pyFlowInstance.graphManager.get().graphChanged.connect(self.onGraphChanged)
        # 连接新建变量按钮的点击信号到 createVariable 方法
        self.pbNewVar.clicked.connect(lambda : self.createVariable())
        # 创建 VariablesListWidget 实例
        self.listWidget = VariablesListWidget()
        # 将 VariablesListWidget 实例添加到布局中
        self.lytListWidget.addWidget(self.listWidget)
        # 连接 PyFlow 实例的新文件执行信号到 actualize 方法
        self.pyFlowInstance.newFileExecuted.connect(self.actualize)

    def actualize(self):
        """
        刷新界面，清除当前列表，然后根据当前激活的图形填充变量列表。
        """
        # 清除列表
        self.clear()
        # 获取当前激活的图形
        graph = self.pyFlowInstance.graphManager.get().activeGraph()
        if graph:
            # 遍历图形中的变量列表
            for var in graph.getVarList():
                # 创建变量包装器并添加到列表中
                self.createVariableWrapperAndAddToList(var)

    def onGraphChanged(self, *args, **kwargs):
        """
        当图形发生改变时，调用 actualize 方法刷新界面。

        :param args: 位置参数
        :param kwargs: 关键字参数
        """
        self.actualize()

    def clear(self):
        """
        清除变量列表，仅影响 UI，不删除任何变量。
        """
        # 清除列表中的所有项
        self.listWidget.clear()

    def killVar(self, uiVariableWidget):
        """
        删除指定的变量，从图形中移除该变量，然后刷新界面，
        并保存操作历史记录。

        :param uiVariableWidget: 要删除的变量的 UI 组件
        """
        # 获取变量所在的图形
        variableGraph = uiVariableWidget._rawVariable.graph
        # 从图形中删除该变量
        variableGraph.killVariable(uiVariableWidget._rawVariable)
        # 刷新界面
        self.actualize()
        # 清除属性视图
        self.clearProperties()
        # 保存操作历史记录
        EditorHistory().saveState("Kill variable", modify=True)

    def createVariableWrapperAndAddToList(self, rawVariable):
        """
        创建变量的 UI 包装器，并将其添加到变量列表中。

        :param rawVariable: 原始的变量对象
        :return: 创建的 UI 变量对象
        """
        # 创建 UI 变量对象
        uiVariable = UIVariable(rawVariable, self)
        # 创建列表项
        item = QListWidgetItem(self.listWidget)
        # 设置列表项的大小提示
        item.setSizeHint(QtCore.QSize(60, 20))
        # 将 UI 变量对象设置为列表项的组件
        self.listWidget.setItemWidget(item, uiVariable)
        return uiVariable

    def createVariable(
        self, dataType="AnyPin", accessLevel=AccessLevel.public, uid=None
    ):
        """
        创建一个新的变量，将其添加到当前激活的图形中，
        并创建对应的 UI 包装器添加到列表中，保存操作历史记录。

        :param dataType: 变量的数据类型，默认为 "AnyPin"
        :param accessLevel: 变量的访问级别，默认为公共级别
        :param uid: 变量的唯一标识符，默认为 None
        :return: 创建的 UI 变量对象
        """
        # 打印变量的数据类型
        print(dataType)
        # 在当前激活的图形中创建新的变量
        rawVariable = (
            self.pyFlowInstance.graphManager.get()
            .activeGraph()
            .createVariable(dataType=dataType, accessLevel=accessLevel, uid=uid)
        )
        # 创建变量的 UI 包装器并添加到列表中
        uiVariable = self.createVariableWrapperAndAddToList(rawVariable)
        # 保存操作历史记录
        EditorHistory().saveState("Create variable", modify=True)
        return uiVariable

    def clearProperties(self):
        """
        清除属性视图，请求 PyFlow 实例清除属性视图。
        """
        self.pyFlowInstance.onRequestClearProperties()

    def onUpdatePropertyView(self, uiVariable):
        """
        更新属性视图，请求 PyFlow 实例填充指定 UI 变量的属性视图。

        :param uiVariable: 要更新属性视图的 UI 变量对象
        """
        self.pyFlowInstance.onRequestFillProperties(uiVariable.createPropertiesWidget)